package com.zhu.instructions.references;

import com.zhu.instructions.base.Index16Instruction;
import com.zhu.rtda.Frame;
import com.zhu.rtda.InstanceOop;
import com.zhu.rtda.OperandStack;
import com.zhu.rtda.heap.InstanceKlass;
import com.zhu.rtda.heap.constant.ClassRef;
import com.zhu.rtda.heap.constant.RuntimeConstantPool;

/**
 * INSTANCEOF 指令：判断对象是否是指定类型的实例。
 *
 * <p>字节码格式：instanceof indexbyte1 indexbyte2 (opcode 0xC1)
 *
 * <p>执行逻辑：
 * <ul>
 *   <li>从操作数栈弹出对象引用（ref）</li>
 *   <li>若 ref 为 null，结果为 0</li>
 *   <li>否则，解析常量池中的 ClassRef 得到目标类</li>
 *   <li>调用 ref 的类的 isAssignableFrom(targetClass) 判断兼容性</li>
 *   <li>将 1 或 0 压入操作数栈</li>
 * </ul>
 */
public class INSTANCE_OF extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        // 1. 弹出对象引用
        OperandStack stack = frame.getOperandStack();
        InstanceOop ref = stack.popRef();

        // 2. null 引用直接返回 false (0)
        if (ref == null) {
            stack.pushInt(0);
            return;
        }

        // 3. 解析目标类
        InstanceKlass currentClass = frame.getMethod().getClazz();
        RuntimeConstantPool cp = currentClass.getConstantPool();
        ClassRef classRef = (ClassRef) cp.getConstant(this.index);
        InstanceKlass targetClass = classRef.resolvedKlass();

        // 4. 判断 ref 的实际类型是否可赋值给 targetClass
        InstanceKlass refClass = ref.getKlass();
        if (targetClass.isAssignableFrom(refClass)) {
            stack.pushInt(1);
        } else {
            stack.pushInt(0);
        }
    }
}